'use strict';

const uidObj = require('uni-id');

const createConfig = require('uni-config-center');
const uidConfig = createConfig({
	pluginId: 'uni-id'
});

const usepayConfig = createConfig({
	pluginId: 'use-pay'
});

const {
	wxpay
} = require('use-api');

const {
	Controller
} = require('uni-cloud-router');
const dbcmd = uniCloud.database().command;

module.exports = class MemberController extends Controller {
	// 用户列表
	async memberList() {
		const response = {
			code: 1,
			total: 0,
			datas: []
		};

		let {
			page,
			rows,
			orderby,
			member_nickname,
			member_mobile,
			member_city,
			member_gender,
			begin_time,
			end_time
		} = this.ctx.data;

		const whereObj = {};

		// 用户名称
		if (member_nickname) {
			whereObj.member_nickname = new RegExp(this.service.utils.filterRegexpKey(member_nickname), 'i');
		}
		// 手机号
		if (member_mobile) {
			whereObj.member_mobile = new RegExp(this.service.utils.filterRegexpKey(member_mobile), 'i');
		}
		// 城市
		if (member_city) {
			whereObj.member_city = new RegExp(this.service.utils.filterRegexpKey(member_city), 'i');
		}
		// 性别
		if (member_gender !== '') {
			whereObj.member_gender = member_gender;
		}
		// 注册时间
		if (begin_time && end_time) {
			whereObj.create_time = dbcmd.gte(begin_time).and(dbcmd.lte(end_time));
		}

		// 总数
		const countRes = await this.db.collection('usemall-member').where(whereObj).count();
		response.total = countRes.total;

		// 排序
		orderby = orderby.split(' ');

		const res = await this.db.collection('usemall-member')
			.where(whereObj)
			.orderBy(orderby[0], orderby[1])
			.field({
				member_headimg: true,
				member_nickname: true,
				is_plus: true,
				member_gender: true,
				member_login_cnt: true,
				member_mobile: true,
				member_city: true,
				member_monetary: true,
				create_time: true
			})
			.skip((page - 1) * rows)
			.limit(rows)
			.get();

		// 判断环境
		const isDevelopment = uidConfig.config('env') === 'dev';

		res.data.forEach(x => {
			// 测试环境下 进行脱敏处理
			if (isDevelopment) {
				x.member_mobile = this.service.utils.desz(x.member_mobile)
			}
		});

		response.code = 0;
		response.datas = res.data;
		return response;
	}

	// 用户详情 - 地址
	async memberDetailAddress() {
		const response = {
			code: 1,
			total: 0,
			datas: []
		};

		let {
			id,
			page,
			rows,
			orderby,
			begin_time,
			end_time
		} = this.ctx.data;

		const whereObj = {
			create_uid: id
		};

		// 创建时间
		if (begin_time && end_time) {
			whereObj.create_time = dbcmd.gte(begin_time).and(dbcmd.lte(end_time));
		}

		// 总数
		const countRes = await this.db.collection('usemall-member-address').where(whereObj).count();
		response.total = countRes.total;

		// 排序
		orderby = orderby.split(' ');

		const res = await this.db.collection('usemall-member-address')
			.where(whereObj)
			.orderBy(orderby[0], orderby[1])
			.field({
				address: true,
				addr_detail: true,
				mobile: true,
				consignee: true,
				remark: true,
				create_time: true
			})
			.skip((page - 1) * rows)
			.limit(rows)
			.get();

		const isDevelopment = uidConfig.config('env') === 'dev';

		res.data.forEach(x => {
			// 测试环境下 进行脱敏处理
			if (isDevelopment) {
				x.consignee =   this.service.utils.desz(x.consignee);
				x.mobile = this.service.utils.desz(x.mobile);
			}
		});

		response.code = 0;
		response.datas = res.data;
		return response;
	}

	// 提现
	async cashout() {
		let response = {
			code: 1,
			datas: ''
		};

		response.msg = '当前提现功能未开启，请自行注释或删除后使用';
		return response;

		let start = Date.now();

		// 请求参数
		const req = this.ctx.data;
		let {
			id,
			type,
			content,
			withdraw_type
		} = req;

		const cashoutRes = await this.db.collection('usemall-member-cashout')
			.doc(id)
			.get();
		const [cashoutData] = cashoutRes.data;

		if (!(cashoutData && cashoutData._id)) {
			response.msg = `当前提现数据不存在`;
			return response;
		}

		const userRes = await this.db.collection('uni-id-users').doc(cashoutData.create_uid).field({
			wx_openid: true,
			wx_unionid: true
		}).get();
		const [user] = userRes.data;

		if (!(user && user._id)) {
			response.msg = `当前提现用户[uni-id-users]数据不存在`;
			return response;
		}

		const walletParameterRes = await this.db.collection('usemall-wallet-parameter').limit(1).get();
		const [walletParameter] = walletParameterRes.data;

		const memberRes = await this.db.collection('usemall-member').doc(cashoutData.uid).get();
		const [memberData] = memberRes.data;

		if (!(memberData && memberData._id)) {
			response.msg = `当前提现用户数据不存在`;
			return response;
		}

		let openid = '';
		// 获取用户 openid
		if (memberData.member_weixin) {
			// 获取用户 openid，优先取 小程序 -> 微信公众号 -> APP
			openid = memberData.member_weixin.mp || memberData.member_weixin.h5 || memberData.member_weixin.app;
		}

		if (!openid) {
			response.msg = `当前提现用户[openid]数据不存在，需进行微信授权登录后申请提现`;
			return response;
		}

		if (type == '已提现') {
			let trade_no = '';
			let transferRes = {};

			if (cashoutData.cashout_way == '微信零钱') {
				trade_no = Date.now() + (Math.round(Math.random() * 1000000) + '').padStart(6, '0');

				// 申请提现金额（单位元）
				const cashout_amount = cashoutData.cashout_amount / 100;
				// 手续费 = 提现金额 * 提现手续费比例 / 100
				const service_charge = cashout_amount * ((walletParameter.service_charge / 100) || 0) >= 0.01 ?
					cashout_amount * ((walletParameter.service_charge / 100) || 0) : 0;
				// 提现金额 = 提现金额 - 手续费
				const amount = (cashout_amount - service_charge).toFixed(2);

				switch (withdraw_type) {
					case 1: // 商家转账到零钱
						const path = require('path');

						const wxpayConfig = usepayConfig.config('wxpayV3');

						const wxOptions = {
							...wxpayConfig,
							appCertPath: path.resolve(__dirname, wxpayConfig.appCertPath),
							appPrivateKeyPath: path.resolve(__dirname, wxpayConfig.appPrivateKeyPath),
							agent: uniCloud.$provider == 'aliyun'
						}

						const wxpayV3 = new wxpay.v3api(wxOptions);

						const res = await wxpayV3.transferBatches({
							out_batch_no: trade_no,
							batch_name: '零钱提现',
							batch_remark: content,
							total_amount: amount * 100,
							total_num: 1,
							transfer_detail_list: [{
								out_detail_no: trade_no,
								transfer_amount: amount * 100,
								transfer_remark: content,
								openid: openid
							}]
						});

						if (res.message) {
							response.msg = res.message;
							return response;
						}

						// 转账数据
						transferRes = res;
						break;
					case 2: // 微信企业付款到零钱
						const url = uidConfig.config('agent.wxpay-transfers');

						const result = await this.curl(url, {
							nestedQuerystring: true,
							method: 'post',
							headers: {
								'Content-Type': 'application/json'
							},
							dataType: 'json',
							data: {
								trade_no: trade_no,
								openid: openid,
								truename: memberData.member_truename,
								check_name: walletParameter
									.check_name, // 是否校验实名合法性 NO_CHECK、FORCE_CHECK、OPTION_CHECK
								amount: amount * 100, // 提现金额（单位分）
								desc: content
							}
						});

						const wxpayRes = result.data;

						if (wxpayRes.code !== 200) {
							response.msg = wxpayRes.msg || wxpayRes.message;
							return response;
						}

						// 付款数据
						transferRes = wxpayRes.datas;
						break;
				}
			}

			try {
				let money =
					`提现金额${cashoutData.cashout_amount / 100}，实际到账${cashoutData.cashout_amount / 100}`;
				if ((cashoutData.cashout_amount / 100) * ((walletParameter.service_charge / 100) || 0) >=
					0.01) {
					money =
						`提现金额${cashoutData.cashout_amount / 100}，扣除手续费${walletParameter.service_charge / 100}，实际到账${this.fmtFloat(cashoutData.cashout_amount / 100 - ((cashoutData.cashout_amount / 100) * (walletParameter.service_charge / 100) || 0))}`;
				}

				// 零钱提现成功 304
				// 不需要 await，只需发送请求即可
				uniCloud.httpclient.request(`${uidConfig.config('message-notify.url')}/304`, {
					method: 'post',
					headers: {
						'message-notify-key': uidConfig.config('message-notify.key')
					},
					timeout: 30 * 1000,
					data: {
						id: cashoutData._id,
						uid: cashoutData.create_uid,
						openid: openid,
						scene: 304,
						uname: cashoutData.create_uname,
						title: '零钱提现已同意',
						money: money,
						way: `${content}`,
						remark: '查看详情'
					},
					contentType: 'json',
					dataType: 'json'
				});
			} catch (e) {
				console.log('message-notify err', e);
			}

			// 提现成功
			// 累计提现金额 profit_amount += 提现金额
			// 待审提现 unprofit_amount -= 提现金额
			await this.db.collection('usemall-member').doc(cashoutData.uid).update({
				profit_amount: this.db.command.inc(cashoutData.cashout_amount),
				unprofit_amount: this.db.command.inc(-cashoutData.cashout_amount),
				version: this.db.command.inc(1)
			});

			let cashoutUpdateObj = {
				payment_no: transferRes.payment_no
			}

			if (withdraw_type == 1) {
				cashoutUpdateObj = {
					payment_no: transferRes.batch_id,
					transfer_status: transferRes.batch_status,
					transfer_time: transferRes.create_time
				};
			}

			await this.db.collection('usemall-member-cashout').doc(id).update({
				trade_no: trade_no,
				...cashoutUpdateObj,
				cashout_desc: content,
				state: type,
				last_modify_time: Date.now(),
				last_modify_uid: this.ctx.auth.uid,
				last_modify_uname: this.ctx.auth.userInfo.username
			});
		} else if (type == '提现失败') {
			try {
				// 零钱提现失败 306
				// 不需要 await，只需发送请求即可
				uniCloud.httpclient.request(`${uidConfig.config('message-notify.url')}/306`, {
					method: 'post',
					headers: {
						'message-notify-key': uidConfig.config('message-notify.key')
					},
					timeout: 30 * 1000,
					data: {
						id: cashoutData._id,
						uid: cashoutData.create_uid,
						openid: openid,
						scene: 306,
						uname: cashoutData.create_uname,
						title: '零钱提现已拒绝',
						money: `${cashoutData.cashout_amount / 100}`,
						way: `${content}`,
						remark: '查看详情'
					},
					contentType: 'json',
					dataType: 'json'
				});
			} catch (e) {
				console.log('message-notify err', e);
			}
			// 提现失败
			// 零钱余额 member_amount += 提现金额
			// 待审提现 unprofit_amount -= 提现金额
			await this.db.collection('usemall-member').doc(cashoutData.uid).update({
				member_amount: this.db.command.inc(cashoutData.cashout_amount),
				unprofit_amount: this.db.command.inc(-cashoutData.cashout_amount),
				version: this.db.command.inc(1)
			});

			await this.db.collection('usemall-member-cashout').doc(id).update({
				cashout_fail: content,
				state: type,
				last_modify_time: Date.now(),
				last_modify_uid: this.ctx.auth.uid,
				last_modify_uname: this.ctx.auth.userInfo.username
			});
		}

		response.datas = '操作成功';

		let end = Date.now();
		console.log(`耗时：${end - start}ms`);
		response.code = 0;
		response.msg = `耗时：${end - start}ms`;
		return response;
	}

	// 查询提现进度
	async getCashoutProgress() {
		let response = {
			code: 1,
			datas: ''
		};

		let start = Date.now();

		// 请求参数
		const req = this.ctx.data;
		let {
			id
		} = req;

		const cashoutRes = await this.db.collection('usemall-member-cashout')
			.doc(id)
			.get();
		const [cashoutData] = cashoutRes.data;

		if (!(cashoutData && cashoutData._id)) {
			response.msg = `当前提现数据不存在`;
			return response;
		}

		switch (cashoutData.withdraw_type) {
			case 1:
				const path = require('path');

				const wxpayConfig = usepayConfig.config('wxpayV3');

				const wxOptions = {
					...wxpayConfig,
					appCertPath: path.resolve(__dirname, wxpayConfig.appCertPath),
					appPrivateKeyPath: path.resolve(__dirname, wxpayConfig.appPrivateKeyPath),
					agent: uniCloud.$provider == 'aliyun'
				}

				const wxpayV3 = new wxpay.v3api(wxOptions);

				const res = await wxpayV3.transferBatchesQuery({
					out_batch_no: cashoutData.trade_no
				});

				if (res && res.code) {
					response.msg = res.message;
					return response;
				}

				response.datas = res.transfer_batch;
				break;
			case 2:
				// 查询微信企业付款到零钱 agent url
				const url = uidConfig.config('agent.wxpay-transfersQuery');

				const result = await this.curl(url, {
					nestedQuerystring: true,
					method: 'post',
					headers: {
						'Content-Type': 'application/json'
					},
					dataType: 'json',
					data: {
						trade_no: cashoutData.trade_no
					}
				});

				response.datas = result.data.datas;
				break;
		}

		let end = Date.now();
		console.log(`耗时：${end - start}ms`);
		response.code = 0;
		response.msg = `耗时：${end - start}ms`;
		return response;
	}

	// 处理精度
	fmtFloat(num) {
		num = parseFloat(num);
		if (isNaN(num)) return num;

		return parseInt(num.toFixed(2) * 100) / 100;
	}
}